﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;

namespace GurLoader.View
{
    [ExcludeFromCodeCoverage]
    public static class ProgressBarHelper
    {
        public static readonly DependencyProperty StopAnimationOnCompletionProperty =
            DependencyProperty.RegisterAttached("StopAnimationOnCompletion", typeof (bool), typeof (ProgressBarHelper),
                new PropertyMetadata(OnStopAnimationOnCompletionChanged));

        private const double FloatEqualityTolerance = .00001f;

        public static bool GetStopAnimationOnCompletion(ProgressBar progressBar)
        {
            return (bool) progressBar.GetValue(StopAnimationOnCompletionProperty);
        }

        public static void SetStopAnimationOnCompletion(ProgressBar progressBar, bool value)
        {
            progressBar.SetValue(StopAnimationOnCompletionProperty, value);
        }

        private static void OnStopAnimationOnCompletionChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs e)
        {
            var progressBar = obj as ProgressBar;
            if (progressBar == null) return;

            var stopAnimationOnCompletion = (bool) e.NewValue;

            if (stopAnimationOnCompletion)
            {
                progressBar.Loaded += StopAnimationOnCompletionLoaded;
                progressBar.ValueChanged += StopAnimationOnCompletionValueChanged;
            }
            else
            {
                progressBar.Loaded -= StopAnimationOnCompletionLoaded;
                progressBar.ValueChanged -= StopAnimationOnCompletionValueChanged;
            }

            if (progressBar.IsLoaded)
            {
                ReevaluateAnimationVisibility(progressBar);
            }
        }

        private static void StopAnimationOnCompletionLoaded(object sender, RoutedEventArgs e)
        {
            ReevaluateAnimationVisibility((ProgressBar) sender);
        }

        private static void StopAnimationOnCompletionValueChanged(object sender,
            RoutedPropertyChangedEventArgs<double> e)
        {
            var progressBar = (ProgressBar) sender;

            if (Math.Abs(e.NewValue - progressBar.Maximum) < FloatEqualityTolerance || Math.Abs(e.OldValue - progressBar.Maximum) < FloatEqualityTolerance)
            {
                ReevaluateAnimationVisibility(progressBar);
            }
        }

        private static void ReevaluateAnimationVisibility(ProgressBar progressBar)
        {
            if (GetStopAnimationOnCompletion(progressBar))
            {
                DependencyObject animationElement = GetAnimationElement(progressBar);
                if (animationElement != null)
                {
                    if (Math.Abs(progressBar.Value - progressBar.Maximum) < FloatEqualityTolerance)
                    {
                        animationElement.SetCurrentValue(UIElement.VisibilityProperty, Visibility.Collapsed);
                    }
                    else
                    {
                        animationElement.InvalidateProperty(UIElement.VisibilityProperty);
                    }
                }
            }
        }

        private static DependencyObject GetAnimationElement(ProgressBar progressBar)
        {
            ControlTemplate template = progressBar.Template;
            if (template == null) return null;

            return template.FindName("PART_GlowRect", progressBar) as DependencyObject;
        }
    }
}